From 71b4557210f07a4e300e8c36740f6b8004f82a54 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Thu, 28 Mar 2013 19:22:42 +0100 Subject: [PATCH] broadway: Sync surface updates with paint clock We now only update surface data after we have painted. Before we painted in an idle, which meant we might send black data some times if we e.g. resized the window and had not painted yet. Also, it means we're updating less often to the daemon, saving resources. We still have to queue a flush in the idle for non-draw operations, otherwise e.g. resize of a toplevel will never be flushed if the clock is frozen (e.g. during toplevel resize). --- gdk/broadway/gdkwindow-broadway.c | 65 ++++++++++++++++++++++++------- 1 file changed, 50 insertions(+), 15 deletions(-) diff --git a/gdk/broadway/gdkwindow-broadway.c b/gdk/broadway/gdkwindow-broadway.c index e9f2b06f1e..02fb04c8e5 100644 --- a/gdk/broadway/gdkwindow-broadway.c +++ b/gdk/broadway/gdkwindow-broadway.c @@ -83,18 +83,16 @@ G_DEFINE_TYPE (GdkWindowImplBroadway, gdk_window_impl_broadway, GDK_TYPE_WINDOW_IMPL) -static guint dirty_flush_id = 0; - -static gboolean -dirty_flush_idle (gpointer data) +static void +update_dirty_windows_and_sync (void) { GList *l; GdkBroadwayDisplay *display; - - dirty_flush_id = 0; + gboolean updated_surface; display = GDK_BROADWAY_DISPLAY (gdk_display_get_default ()); + updated_surface = FALSE; for (l = display->toplevels; l != NULL; l = l->next) { GdkWindowImplBroadway *impl = l->data; @@ -102,6 +100,7 @@ dirty_flush_idle (gpointer data) if (impl->dirty) { impl->dirty = FALSE; + updated_surface = TRUE; _gdk_broadway_server_window_update (display->server, impl->id, impl->surface); @@ -110,16 +109,32 @@ dirty_flush_idle (gpointer data) /* We sync here to ensure all references to the impl->surface memory is done, as we may later paint new data in them. */ - gdk_display_sync (GDK_DISPLAY (display)); + if (updated_surface) + gdk_display_sync (GDK_DISPLAY (display)); + else + gdk_display_flush (GDK_DISPLAY (display)); +} + +static guint flush_id = 0; + +static gboolean +flush_idle (gpointer data) +{ + flush_id = 0; + + gdk_display_flush (gdk_display_get_default ()); return FALSE; } +/* We need to flush in an idle rather than AFTER_PAINT, as the clock + is frozen during e.g. window resizes so the paint will not happen + and the window resize request is never flushed. */ static void -queue_dirty_flush (GdkBroadwayDisplay *display) +queue_flush (GdkWindow *window) { - if (dirty_flush_id == 0) - dirty_flush_id = gdk_threads_add_idle (dirty_flush_idle, NULL); + if (flush_id == 0) + flush_id = gdk_threads_add_idle (flush_idle, NULL); } static void @@ -197,6 +212,25 @@ _gdk_broadway_screen_init_root_window (GdkScreen * screen) _gdk_window_update_size (broadway_screen->root_window); } +static void +on_frame_clock_after_paint (GdkFrameClock *clock, + GdkWindow *window) +{ + update_dirty_windows_and_sync (); +} + +static void +connect_frame_clock (GdkWindow *window) +{ + if (WINDOW_IS_TOPLEVEL (window)) + { + GdkFrameClock *frame_clock = gdk_window_get_frame_clock (window); + + g_signal_connect (frame_clock, "after-paint", + G_CALLBACK (on_frame_clock_after_paint), window); + } +} + void _gdk_broadway_display_create_window_impl (GdkDisplay *display, GdkWindow *window, @@ -229,6 +263,8 @@ _gdk_broadway_display_create_window_impl (GdkDisplay *display, g_assert (GDK_WINDOW_TYPE (window->parent) == GDK_WINDOW_ROOT); broadway_display->toplevels = g_list_prepend (broadway_display->toplevels, impl); + + connect_frame_clock (window); } void @@ -384,7 +420,7 @@ gdk_window_broadway_show (GdkWindow *window, gboolean already_mapped) broadway_display = GDK_BROADWAY_DISPLAY (gdk_window_get_display (window)); if (_gdk_broadway_server_window_show (broadway_display->server, impl->id)) - queue_dirty_flush (broadway_display); + queue_flush (window); } @@ -405,7 +441,7 @@ gdk_window_broadway_hide (GdkWindow *window) broadway_display = GDK_BROADWAY_DISPLAY (gdk_window_get_display (window)); if (_gdk_broadway_server_window_hide (broadway_display->server, impl->id)) - queue_dirty_flush (broadway_display); + queue_flush (window); _gdk_window_clear_update_area (window); } @@ -460,7 +496,7 @@ gdk_window_broadway_move_resize (GdkWindow *window, with_move, x, y, window->width, window->height); - queue_dirty_flush (broadway_display); + queue_flush (window); if (size_changed) window->resize_count++; } @@ -1327,7 +1363,6 @@ gdk_broadway_window_process_updates_recurse (GdkWindow *window, impl = GDK_WINDOW_IMPL_BROADWAY (window->impl); impl->dirty = TRUE; - queue_dirty_flush (GDK_BROADWAY_DISPLAY (gdk_window_get_display (window))); } void @@ -1393,7 +1428,7 @@ _gdk_broadway_window_translate (GdkWindow *window, if (_gdk_broadway_server_window_translate (broadway_display->server, impl->id, area, dx, dy)) - queue_dirty_flush (broadway_display); + queue_flush (window); } } -- 2.30.2